#ifndef __DefaultHardwareBufferManager_H__
#define __DefaultHardwareBufferManager_H__

#include "U2PreRequest.h"
#include "U2HardwareBufferManager.h"
#include "U2HardwareVertexBuffer.h"
#include "U2HardwareIndexBuffer.h"


U2EG_NAMESPACE_BEGIN


/// Specialisation of U2HardwareVertexBuffer for emulation
class _U2Share U2DefaultHardwareVertexBuffer : public U2HardwareVertexBuffer 
{
protected:
	unsigned char* mpData;
    /** See U2HardwareBuffer. */
    void* lockImpl(size_t offset, size_t length, LockOptions options);
    /** See U2HardwareBuffer. */
	void unlockImpl(void);
public:
	U2DefaultHardwareVertexBuffer(size_t vertexSize, size_t numVertices, U2HardwareBuffer::Usage usage);
	U2DefaultHardwareVertexBuffer(U2HardwareBufferManagerBase* mgr, size_t vertexSize, size_t numVertices, 
        U2HardwareBuffer::Usage usage);
    ~U2DefaultHardwareVertexBuffer();
    /** See U2HardwareBuffer. */
    void readData(size_t offset, size_t length, void* pDest);
    /** See U2HardwareBuffer. */
    void writeData(size_t offset, size_t length, const void* pSource,
			bool discardWholeBuffer = false);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void* lock(size_t offset, size_t length, LockOptions options);
    /** Override U2HardwareBuffer to turn off all shadowing. */
	void unlock(void);
};


/// Specialisation of U2HardwareIndexBuffer for emulation
class _U2Share U2DefaultHardwareIndexBuffer : public U2HardwareIndexBuffer
{
protected:
	unsigned char* mpData;
    /** See U2HardwareBuffer. */
    void* lockImpl(size_t offset, size_t length, LockOptions options);
    /** See U2HardwareBuffer. */
	void unlockImpl(void);
public:
	U2DefaultHardwareIndexBuffer(IndexType idxType, size_t numIndexes, U2HardwareBuffer::Usage usage);
    ~U2DefaultHardwareIndexBuffer();
    /** See U2HardwareBuffer. */
    void readData(size_t offset, size_t length, void* pDest);
    /** See U2HardwareBuffer. */
    void writeData(size_t offset, size_t length, const void* pSource,
			bool discardWholeBuffer = false);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void* lock(size_t offset, size_t length, LockOptions options);
    /** Override U2HardwareBuffer to turn off all shadowing. */
	void unlock(void);

};


/** Specialisation of U2HardwareBufferManagerBase to emulate hardware buffers.
@remarks
	You might want to instantiate this class if you want to utilise
	classes like MeshSerializer without having initialised the 
	rendering system (which is required to create a 'real' hardware
	buffer manager.
*/
class _U2Share U2DefaultHardwareBufferManagerBase : public U2HardwareBufferManagerBase
{
public:
    U2DefaultHardwareBufferManagerBase();
    ~U2DefaultHardwareBufferManagerBase();
    /// Creates a vertex buffer
	U2HardwareVertexBufferSharedPtr 
        createVertexBuffer(size_t vertexSize, size_t numVerts, 
			U2HardwareBuffer::Usage usage, bool useShadowBuffer = false);
	/// Create a hardware vertex buffer
	U2HardwareIndexBufferSharedPtr 
        createIndexBuffer(U2HardwareIndexBuffer::IndexType itype, size_t numIndexes, 
			U2HardwareBuffer::Usage usage, bool useShadowBuffer = false);
};


/// U2DefaultHardwareBufferManager as a Singleton
class _U2Share U2DefaultHardwareBufferManager : public U2HardwareBufferManager
{
public:
	U2DefaultHardwareBufferManager()
		: U2HardwareBufferManager(U2_NEW U2DefaultHardwareBufferManagerBase()) 
	{

	}
	~U2DefaultHardwareBufferManager()
	{
		U2_DELETE mImpl;
	}
};


U2EG_NAMESPACE_END

#endif
